package com.sky.service.impl;

import cn.hutool.core.util.StrUtil;
import com.sky.entity.Orders;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WorkspaceService workspaceService;
    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        List<LocalDate> dateList = getDateList(begin, end);

        List<Double> turnoverList = dateList.stream().map(date -> {
            Double sum = orderMapper.findStatusAndTime(Orders.COMPLETED, date);
            return sum;
        }).collect(Collectors.toList());
        String s = StrUtil.join(",", dateList);
        String t = StrUtil.join(",", turnoverList);
        return TurnoverReportVO.builder()
                .dateList(s)
                .turnoverList(t)
                .build();

    }

    @Override
    public UserReportVO UserStat(LocalDate begin, LocalDate end) {
        List<LocalDate> dateList = getDateList(begin, end);
        List<Integer> newUserList=new ArrayList<>();
        List<Integer> totalUserList=new ArrayList<>();
        int totalUser=0;
        for (LocalDate date : dateList) {
            Integer countUser =userMapper.countUserByDate(date);

            newUserList.add(countUser);

            totalUser+=countUser;
            totalUserList.add(totalUser);
        }
        return UserReportVO.builder()
                .newUserList(StrUtil.join(",",newUserList))
                .dateList(StrUtil.join(",",dateList))
                .totalUserList(StrUtil.join(",",totalUserList))
                .build();
    }

    @Override
    public OrderReportVO ordersStat(LocalDate begin, LocalDate end) {
        List<LocalDate> dateList = getDateList(begin, end);
        List<Integer> orderCountList =new ArrayList<>();
        List<Integer> validOrderCountList =new ArrayList<>();

        int totalOrderCount=0;
        int validOrderCount=0;
        for (LocalDate date : dateList) {
           Integer dayTotalOrderCount = orderMapper.findStatusAndDate(null,date);
           Integer dayValidOrderCount = orderMapper.findStatusAndDate(Orders.COMPLETED,date);

           orderCountList.add(dayTotalOrderCount);
           validOrderCountList.add(dayValidOrderCount);
           totalOrderCount+=dayTotalOrderCount;
           validOrderCount+=dayValidOrderCount;
        }
        Double completionRate =0.0;
        if(totalOrderCount!=0){
           completionRate= BigDecimal.valueOf(validOrderCount).divide(BigDecimal.valueOf(totalOrderCount),2, RoundingMode.HALF_UP).doubleValue();
        }
        return OrderReportVO.builder()
                .dateList(StrUtil.join(",",dateList))
                .orderCountList(StrUtil.join(",",orderCountList))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validOrderCount)
                .validOrderCountList(StrUtil.join(",",validOrderCountList))
                .orderCompletionRate(completionRate)
                .build();


    }

    @Override
    public SalesTop10ReportVO saleTop10(LocalDate begin, LocalDate end) {

        List<Map<String,Object>> mapList =orderMapper.findSaleTop10(begin,end);

        List<Object> nameList = mapList.stream().map(map -> {
            Object name = map.get("name");
            return name;
        }).collect(Collectors.toList());
        List<Object> numberList = mapList.stream().map(map -> {
            Object number = map.get("number");
            return number;
        }).collect(Collectors.toList());

        return SalesTop10ReportVO.builder()
                .nameList(StrUtil.join(",",nameList))
                .numberList(StrUtil.join(",",numberList))
                .build();

    }

    @Override
    public Map<String, Object> export() {
        LocalDate beginTime =LocalDate.now().minusDays(30);
        LocalDate endTime =LocalDate.now().minusDays(1);

        double turnover =0.0;
        int newUsers = 0;
        int validOrderCount = 0;
        int totalOrderCount = 0;

        List<BusinessDataVO> voList = new ArrayList<>();
        for (int i = 0; i <30 ; i++) {
            LocalDate date =beginTime.plusDays(i);
            BusinessDataVO vo = workspaceService.businessData(date);
            vo.setDate(date);
            voList.add(vo);
            turnover+=vo.getTurnover();
            newUsers+=vo.getNewUsers();
            validOrderCount+=vo.getValidOrderCount();
            totalOrderCount+=vo.getTotal();
        }
        double orderCompletionRate =0.0;
        if(totalOrderCount!=0){
            orderCompletionRate = BigDecimal.valueOf(validOrderCount)
                    .divide(BigDecimal.valueOf(totalOrderCount),2,RoundingMode.HALF_UP)
                    .doubleValue();
        }
        double unitPrice =0.0;
        if(validOrderCount!=0){
            unitPrice = BigDecimal.valueOf(turnover)
                    .divide(BigDecimal.valueOf(validOrderCount),2,RoundingMode.HALF_UP)
                    .doubleValue();
        }
        BusinessDataVO vo = BusinessDataVO.builder()
                .turnover(turnover)
                .orderCompletionRate(orderCompletionRate)
                .newUsers(newUsers)
                .validOrderCount(validOrderCount)
                .unitPrice(unitPrice)
                .beginTime(beginTime)
                .endTime(endTime)
                .total(voList.size())
                .build();
        Map<String,Object> map = new HashMap<>();
        map.put("list",voList);
        map.put("vo",vo);
        return map;
    }

    private List<LocalDate> getDateList(LocalDate begin, LocalDate end) {
        List<LocalDate> dateList =new ArrayList<>();
        dateList.add(begin);
        while (!begin.equals(end)){
            begin = begin.plusDays(1);
            dateList.add(begin);
        }
        return dateList;
    }
}
